package com.chameleon.sqltranslator.dialect.mysql.util;

import com.alibaba.druid.sql.SQLTransformUtils;
import com.alibaba.druid.sql.ast.*;
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
import com.alibaba.druid.sql.ast.statement.SQLCharacterDataType;
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
import com.alibaba.druid.sql.ast.statement.SQLPartitionRef;
import com.alibaba.druid.util.FnvHash.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

public class OpenGuassDataTypeTransformUtil extends SQLTransformUtils {
    private final static Logger logger= LoggerFactory.getLogger(OpenGuassDataTypeTransformUtil.class);
    private final static String MEDIUMINT = "MEDIUMINT";
    private final static String SMALLINT = "SMALLINT";
    private final static String INTEGER = "INTEGER";
    private final static String BIGINT = "BIGINT";
    private final static String BIGSERIAL = "BIGSERIAL";
    public static SQLDataType transfromOpenGaussToMysql(SQLDataType x) {
        String name = x.getName().toUpperCase();
        long nameHash = x.nameHashCode64();
        List<SQLExpr> arguments = x.getArguments();
        SQLDataType dataType;
        SQLExpr arg0;
        int precision;
        SQLObject parent = x.getParent();
        boolean isAutoIncrement = parent instanceof SQLColumnDefinition && ((SQLColumnDefinition) parent).isAutoIncrement();
        if (x.isInt() || name.equals(MEDIUMINT)) {
            if(arguments.size() == 0) {
                if (isAutoIncrement){
                    dataType = new SQLDataTypeImpl(BIGSERIAL);
                }else if (nameHash == Constants.TINYINT) {
                    dataType = new SQLDataTypeImpl(SMALLINT);
                }else if (name.equals(MEDIUMINT)){
                    dataType = new SQLDataTypeImpl(INTEGER);
                }else if (nameHash == Constants.INT){
                    dataType = new SQLDataTypeImpl(INTEGER);
                }else {
                    dataType = new SQLDataTypeImpl(name);
                }
            }
            else {
               arg0 = arguments.get(0);
               precision = ((SQLIntegerExpr)arg0).getNumber().intValue();
               if (precision <= 20 && isAutoIncrement) {
                  dataType = new SQLDataTypeImpl(BIGSERIAL);
               }else if (precision < 5) {
                   dataType = new SQLDataTypeImpl(SMALLINT);
               } else if (precision < 9) {
                   dataType = new SQLDataTypeImpl(INTEGER);
               } else if (precision <= 20) {
                   dataType = new SQLDataTypeImpl(BIGINT);
               } else {
                   if (isAutoIncrement) {
                       logger.warn("openGauss only support auto increment on integer <= bigint");
                   }
                   dataType = new SQLDataTypeImpl("DECIMAL", precision);
               }
            }
        }
        else if (nameHash == Constants.FLOAT || nameHash == Constants.DOUBLE || nameHash == Constants.DOUBLE_PRECISION ||
        nameHash == Constants.REAL){
            if (isAutoIncrement) {
                logger.warn("openGauss only support int autoincrement");
            }
            if (arguments.size() > 0){
                arg0 = arguments.get(0);
                precision = ((SQLIntegerExpr)arg0).getNumber().intValue();
                dataType = new SQLCharacterDataType("FLOAT", precision);
            }else if(nameHash == Constants.DOUBLE){
                dataType = new SQLDataTypeImpl("DOUBLE PRECISION");
            }else {
                dataType = x;
            }
        } else if(nameHash == Constants.TIME || nameHash == Constants.TIMESTAMP || nameHash == Constants.DATE ||
        nameHash == Constants.DATETIME || nameHash == Constants.YEAR){
            if (nameHash == Constants.YEAR) {
                logger.error("openGauss doesn't support year(n)");
            }
            dataType = x.clone();
            if (nameHash == Constants.DATETIME) {
               dataType.setName("TIMESTAMP");
            }
        }
        else if(nameHash == Constants.TINYTEXT || nameHash == Constants.MEDIUMTEXT || nameHash == Constants.LONGTEXT
        || nameHash == Constants.TEXT) {
            dataType = new SQLDataTypeImpl("TEXT");
        }
        else if(nameHash == Constants.BINARY || nameHash == Constants.VARBINARY ){
            dataType = new SQLDataTypeImpl("BYTEA");
        }
        else if(nameHash == Constants.TINYBLOB || nameHash == Constants.BLOB
                || nameHash == Constants.LONGBLOB || name.equals("MEDIUMBLOB")){
            dataType = new SQLDataTypeImpl("BLOB");
        }
        else if (nameHash == Constants.ENUM || nameHash == Constants.SET || nameHash == Constants.JSON){
            logger.error("NOT SUPPORT TYPE " + x.getName());
            dataType = x;
        }
        else{
            dataType = x;
        }
        if (dataType != x) {
            dataType.setParent(x.getParent());
        }
        return dataType;

    }

    public static boolean checkPartitionDataType(SQLPartitionBy x){
        return false;
    }
}
